<?php

namespace app\api\model\order;

use app\api\model\plus\coupon\UserCoupon;
use app\api\model\plus\discount\Product as DiscountProductModel;
use app\api\model\product\Product as ProductModel;
use app\api\model\settings\DicModel;
use app\api\model\store\Clerk;
use app\api\model\store\Store;
use app\api\model\supplier\Supplier;
use app\api\model\user\User;
use app\api\model\user\UserAddress;
use app\api\service\order\LakalaPaymentService;
use app\api\service\order\paysuccess\type\MasterPaySuccessService;
use app\api\service\order\PaymentService;
use app\api\model\settings\Setting as SettingModel;
use app\common\enum\order\OrderPayTypeEnum;
use app\common\enum\order\OrderSourceEnum;
use app\common\enum\order\OrderTypeEnum;
use app\common\enum\order\OrderPayStatusEnum;
use app\common\enum\order\OrderStatusEnum;
use app\common\exception\BaseException;
use app\common\library\sms\Driver as SmsDriver;
use app\common\model\european\EuropeanUserPicking;
use app\common\model\product\ProductClaim;
use app\common\model\sms\Sms;
use app\common\model\stall\Product as StallProductModel;
use app\common\model\supplier\SupplierCommission;
use app\common\service\order\OrderCompleteService;
use app\common\enum\settings\DeliveryTypeEnum;
use app\common\library\helper;
use app\common\model\order\Order as OrderModel;
use app\api\service\order\checkpay\CheckPayFactory;
use app\common\service\product\factory\ProductFactory;
use app\common\model\plus\coupon\UserCoupon as UserCouponModel;
use app\common\model\order\OrderTrade as OrderTradeModel;
use app\common\model\order\OrderReferee as OrderRefereeModel;
use app\common\service\order\OrderRefundService;
use app\common\model\user\User as UserModel;
use app\common\model\shopper\Shopper;
use app\common\model\product\Category as CategoryModel;
use app\common\model\order\OrderProduct;
use app\Request;
use think\Exception;
use think\facade\Db;

/**
 * 普通订单模型
 */
class Order extends OrderModel
{
    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = [
        'update_time'
    ];


    /**
     * 订单支付事件
     */
    public function onPay($params, $user)
    {
        $orderID = explode(',', $params['order_id']);
        if (count($orderID) == 1) {
            $order = self::getUserOrderDetail($params['order_id'], $user['user_id']);
            // 判断订单状态
            $checkPay = CheckPayFactory::getFactory($order['order_source']);

            if (!$checkPay->checkOrderStatus($order)) {
                $this->error = $checkPay->getError();
                return false;
            }
        }
        return true;
    }

    /**
     * 用户中心订单列表
     */
    public function getList($user_id, $type, $params)
    {
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case 'delivery';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'comment';
                $filter['is_comment'] = 0;
                $filter['order_status'] = 30;
                $filter['is_order_refund'] = 0;
                break;
        }
        $model = new self;
        if (isset($params['shop_supplier_id']) && $params['shop_supplier_id']) {
            $model = $model->where('shop_supplier_id', '=', $params['shop_supplier_id']);
        } else {
            // 用户查询
            $model = $model->where('user_id', '=', $user_id);
        }
        $list = $model->with(['product.image', 'supplier', 'advance', 'gift_product_order' => ['gift_product', 'file']])
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc'])
            ->paginate($params);
        foreach ($list as &$item) {
            $timestamp = strtotime($item['create_time']);
            $month_time = 30 * 24 * 3600 + $timestamp;//一个月内的订单可以开票

            $is_ticket = 0;
            if ($month_time >= time()) {
                $is_ticket = 1;
            }
            $item['is_ticket'] = $is_ticket;

            if ($item['pay_status']['value'] == 10 && $item['order_status']['value'] != 20 && $item['pay_end_time'] != 0) {
                $item['pay_end_time_format'] = $this->formatPayEndTime($item['pay_end_time'] - time());
            } else {
                $item['pay_end_time_format'] = '';
            }
        }
        return $list;
    }

    /**
     * 获取所有订单信息
     * @param $user_id
     * @param $type
     * @param $params
     * @return \think\Paginator
     * @throws \think\db\exception\DbException
     */
    public function getDeliveryList($type, $params, $user, $is_shopper = 0)
    {
        $clerk = Clerk::getByUser($user);
        $is_rest = 1;
        $shopper = [];
        if ($is_shopper != 1) { //特殊配送员不做这个判断
            if (empty($clerk)) {
                throw new Exception('用户不是配送员');
            }
            $is_rest = $clerk['is_rest'];
        } else {
            $shopper = Shopper::shopperDetail($user['user_id']);
            $is_rest = $shopper['is_rest'];
        }

        // 筛选条件
        $filter = [];
        // 订单数据类型
        if($is_rest == 2){ ////如果店员休息的话就不再显示待接订单
            return [];
        }
        $this->_getDeliveryFilter($filter, $type, $clerk, $shopper, $is_rest, $user);
        $model = new self;

        if ($type == 'delivery') {
            if ($params['order_source'] == 30) {
                $model = $model->where('order_source', '=', 30);
                $model = $model->where('assemble_status', '=', 20);
            } else {
                $model = $model->where('order_source', '<>', 30);
            }
        }

        if (isset($params['start_time']) && $params['start_time'] && isset($params['end_time']) && $params['end_time']) {
            $start_time = strtotime($params['start_time']);
            $end_time = strtotime($params['end_time']) + 24 * 3600;
            $model = $model->where('create_time', '>=', $start_time);
            $model = $model->where('create_time', '<', $end_time);
        }

        if (isset($params['keywords']) && $params['keywords']) {
            $map[] = ['product_name', 'like', "%" . $params['keywords'] . "%"];
            $order_ids = (new OrderProduct())->where($map)->column('order_id');
            $model = $model->where('order_id', 'in', $order_ids);
        }


        $list = $model->with(['product.image', 'supplier', 'advance', 'address', 'gift_product_order' => ['gift_product', 'file']])
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc'])
            ->paginate($params);

        foreach ($list as $key => $item) {
            if ($item['pay_status']['value'] == 10 && $item['order_status']['value'] != 20 && $item['pay_end_time'] != 0) {
                $item['pay_end_time_format'] = $this->formatPayEndTime($item['pay_end_time'] - time());
            } else {
                $item['pay_end_time_format'] = '';
            }
        }
        return $list;
    }

    /**
     * @Exp    获取配送员订单数量
     * @Author Mr.Z
     * @Date   2024-03-07
     * @param  [type]     $type       [description]
     * @param  [type]     $params     [description]
     * @param  [type]     $user       [description]
     * @param integer $is_shopper [description]
     * @return [type]                 [description]
     */
    public function getDeliveryCount($type, $params, $user, $is_shopper = 0)
    {
        $clerk = Clerk::getByUser($user);
        if ($is_shopper != 1) { //特殊配送员不做这个判断
            if (empty($clerk)) {
                return 0;
            }
        }
        $shopper = Shopper::shopperDetail($user['user_id']);
        // 筛选条件
        $filter = [];
        // 订单数据类型
        $this->_getDeliveryFilter($filter, $type, $clerk, $shopper, 1, $user);
        $model = new self;
        if ($type == 'delivery') {
            if (isset($params['order_source'])) {
                if ($params['order_source'] == 30) {
                    $model = $model->where('order_source', '=', 30);
                    $model = $model->where('assemble_status', '=', 20);
                } else {
                    $model = $model->where('order_source', '<>', 30);
                }
            } else {
                $model = $model->where('order_source', '<>', 30);
            }
        }
        if (isset($params['start_time']) && $params['start_time'] && isset($params['end_time']) && $params['end_time']) {
            $start_time = strtotime($params['start_time']);
            $end_time = strtotime($params['end_time']) + 24 * 3600;
            $model = $model->where('create_time', '>=', $start_time);
            $model = $model->where('create_time', '<', $end_time);
        }
        if (isset($params['keywords']) && $params['keywords']) {
            $map[] = ['product_name', 'like', "%" . $params['keywords'] . "%"];
            $order_ids = (new OrderProduct())->where($map)->column('order_id');
            $model = $model->where('order_id', 'in', $order_ids);
        }

        $Xcount = $model->where($filter)->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc'])
            ->count();
        return $Xcount;
    }

    /**
     * @Exp    获取配送员订单条件
     * @Author Mr.Z
     * @Date   2024-03-07
     * @param  [Array]    $filter     [_&_返回数据]
     * @param  [type]     $type       [类型]
     * @param  [type]     $clerk      [跑腿]
     * @param  [type]     $shopper    [特殊跑腿]
     */
    private function _getDeliveryFilter(&$filter, $type, $clerk, $shopper, $is_rest = 1, $user)
    {
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case 'delivery'; //接单中
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'comment';
//                $filter['is_comment'] = 0;
                $filter['order_status'] = 30;
                break;
            case 'shipping'; //特殊配送员接单
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['order_status'] = 10;//订单状态10=>进行中，20=>已经取消，30=>已完成
                $filter['is_transfer'] = 1;//是否转单0=未转单，1=已转单,
                $filter['is_clerk_shipping'] = 0;//是否转单0=未接单，1=已接单
                $filter['is_single'] = 0;
//                $filter['delivery_status'] = 10;
                break;
            case 'received_order'; //特殊配送员接单
                $filter['is_transfer'] = 1;//是否转单0=未转单，1=已转单,
//                $filter['is_clerk_shipping'] = 1;//是否转单0=未接单，1=已接单
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                $filter['is_single'] = 1;
                break;
            case 'shopper_comment';//特殊配送员完成的订单
//                $filter['is_comment'] = 0;
                $filter['order_status'] = 30;
                break;
        }
        if ($type == 'delivery') { //接单中

            $filter['store_id'] = $clerk['store_id'];
        } else if ($type == 'received' || $type == 'comment') {
//            $filter['store_clerk_id|transfer_ckid'] = $clerk['clerk_id'];
            $filter[] = ['user_id_json', 'like', '%"' . $user['user_id'] . '"%'];
        } else if ($type == 'shipping' || $type == 'received_order' || $type == 'shopper_comment') {
//            $filter['shopper_id'] = $shopper['id'];
            $filter[] = ['user_id_json', 'like', '%"' . $user['user_id'] . '"%'];

//            $filter['store_clerk_id|transfer_ckid'] = $shopper['id'];

        } else {
            return;
        }
    }

    /**
     * 用户中心拼团订单列表
     */
    public function getAssembleList($user_id, $params)
    {
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($params['type']) {
            case '10'://所有订单
                break;
            case '20';//待支付订单
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case '30';//拼团中
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['assemble_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case '40';//拼团成功
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['assemble_status'] = 20;
                break;
            case '50';//拼团失败
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['assemble_status'] = 30;
                break;
        }
        $list = $this->with(['product.image', 'supplier', 'advance'])
            ->where('user_id', '=', $user_id)
            ->where('order_source', '=', OrderSourceEnum::ASSEMBLE)
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc'])
            ->paginate($params);
        foreach ($list as &$item) {
            if ($item['pay_status']['value'] == 10 && $item['order_status']['value'] != 20 && $item['pay_end_time'] != 0) {
                $item['pay_end_time_format'] = $this->formatPayEndTime($item['pay_end_time'] - time());
            } else {
                $item['pay_end_time_format'] = '';
            }
        }
        return $list;
    }

    /**
     * 确认收货
     */
    public function receipt()
    {
        // 验证订单是否合法
        // 条件1: 订单必须已发货
        // 条件2: 订单必须未收货
        if ($this['delivery_status']['value'] != 20 || $this['receipt_status']['value'] != 10) {
            $this->error = '该订单不合法';
            return false;
        }
        return $this->transaction(function () {
            // 更新订单状态
            $status = $this->save([
                'receipt_status' => 20,
                'receipt_time' => time(),
                'order_status' => 30
            ]);
            // 执行订单完成后的操作
            $OrderCompleteService = new OrderCompleteService(OrderTypeEnum::MASTER);
            $OrderCompleteService->complete([$this], static::$app_id);
            return $status;
        });
    }

    /**
     * 立即购买：获取订单商品列表
     */
    public static function getOrderProductListByNow($params)
    {
        // 商品详情
        $product = ProductModel::detail($params['product_id']);
        // 商品sku信息
        $product['product_sku'] = ProductModel::getProductSku($product, $params['product_sku_id']);
        // 商品分类信息
        $product['categorydetail'] = CategoryModel::detail($product['category_id'])->visible(['category_id', 'type']);
        // 商品列表
        $productList = [$product->hidden(['category', 'content', 'image', 'sku'])];
        foreach ($productList as &$item) {
            $OldPrice = $item['product_sku']['product_price'];
            // 商品单价
            $newrs = StallProductModel::checkDB($params['stall_id']??0, $item['product_id']);
            if (isset($newrs['product_price'])&&$newrs['product_price']>0) {
                $addPrices = $newrs['product_price'];
                $item['product_sku']['product_price'] = bcadd($OldPrice, $addPrices, 2);
            }
            $item['product_price'] = $item['product_sku']['product_price'];
            // 商品购买数量
            $item['total_num'] = $params['product_num'];
            $item['spec_sku_id'] = $item['product_sku']['spec_sku_id'];
            // 商品购买总金额
            $item['total_price'] = helper::bcmul($item['product_price'], $params['product_num']);
        }
        $supplierData[] = [
            'shop_supplier_id' => $product['shop_supplier_id'],
            'supplier' => $product['supplier'],
            'productList' => $productList
        ];
        unset($product['supplier']);
        return $supplierData;
    }

    /**
     * 获取订单总数
     */
    public function getCount($user, $type = 'all', $nowhere = false)
    {
        if ($user === false) {
            return false;
        }
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                break;
            case 'delivery';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'comment';
                $filter['order_status'] = 30;
                $filter['is_comment'] = 0;
                $filter['is_order_refund'] = 0;
                break;
        }
        if ($nowhere) {
            return $this->getMyorderNum($user['user_id']);
        } else {
            return $this->where('user_id', '=', $user['user_id'])
                ->where('order_status', '<>', 20)
                ->where($filter)
                ->where('is_delete', '=', 0)
                ->count();
        }
    }

    /**
     * 取消订单
     */
    public function cancel($user)
    {
        if ($this['delivery_status']['value'] == 20) {
            $this->error = '已发货订单不可取消';
            return false;
        }
        //进行中的拼团订单不能取消
        if ($this['order_source'] == OrderSourceEnum::ASSEMBLE) {
            if ($this['assemble_status'] == 10) {
                $this->error = '订单正在拼团，到期后如果订单未拼团成功将自动退款';
                return false;
            }
        }
        // 订单取消事件
        return $this->transaction(function () use ($user) {
            // 订单是否已支付
            $isPay = $this['pay_status']['value'] == OrderPayStatusEnum::SUCCESS;
            // 未付款的订单
            if ($isPay == false) {
                //主商品退回库存
                ProductFactory::getFactory($this['order_source'])->backProductStock($this['product'], $isPay);
                // 回退用户优惠券
                $this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
                $this['coupon_id_sys'] > 0 && UserCouponModel::setIsUse($this['coupon_id_sys'], false);
                // 回退用户积分
                $describe = "订单取消：{$this['order_no']}";
                $this['points_num'] > 0 && $user->setIncPoints($this['points_num'], $describe);
                //判断是否为预售订单
                if ($this['order_source'] == OrderSourceEnum::ADVANCE) {
                    if ($this['advance']['money_return'] == 1) {//预售订单退定金
                        if ((new OrderRefundService)->execute($this['advance'])) {
                            // 更新订单状态
                            $this['advance']->save([
                                'is_refund' => 1,
                                'refund_money' => $this['advance']['pay_price'],
                            ]);
                        }
                    }
                    $this['advance']->save(['order_status' => 20]);
                }
            }
            // 更新订单状态
            return $this->save(['order_status' => $isPay ? OrderStatusEnum::APPLY_CANCEL : OrderStatusEnum::CANCELLED]);
        });
    }

    /**
     * 订单详情
     */
    public static function getUserOrderDetail($order_id, $user_id)
    {
        $model = new static();
        $order = $model->where(['order_id' => $order_id, 'user_id' => $user_id])->with(['product' => ['image', 'refund'], 'address', 'express', 'extractStore', 'supplier', 'advance', 'gift_product_order' => ['gift_product', 'file']])->find();
        $category_list = (new CategoryModel())->column('type', 'category_id');

        $order['deliveryUser'] = $model::getDeliveryUser($order['store_clerk_id'], $order['is_store_clerk_id']);

        $discount_product_data = (new DiscountProductModel())->getDiscountAtivityProduct(); //限时优惠商品id
        $product_type = 'pt';
        foreach ($order['product'] as $key => $value) {
            $product_id = $value['product_id'];
            $product_data = (new ProductModel())->where('product_id', $product_id)->field('category_id,is_show')->find();
            $category_id = $product_data['category_id'];
            $is_show = $product_data['is_show'];
            $is_click = $category_list[$category_id] ?? 0;
            $value['is_click'] = $is_click;

            $value['discount_product_data'] = [];
            if (isset($discount_product_data[$product_id]) && $discount_product_data[$product_id]) {
                $value['discount_product_data'] = $discount_product_data[$product_id];
                $product_type = 'discount';
            } else {
                $product_type = $is_show == 1 ? 'pt' : 'ts';
            }

//            if(in_array($product_id,$discount_product_ids)){
//                $product_type = 'discount';
//            }else{
//                $product_type = $is_show == 1 ?'pt':'ts';
//            }

            $value['product_type'] = $product_type;

            $order['product'][$key] = $value;
        }


        if (empty($order)) {
            throw new BaseException(['msg' => '订单不存在']);
        }

        $timestamp = strtotime($order['create_time']);
        $month_time = 30 * 24 * 3600 + $timestamp;//一个月内的订单可以开票

        $is_ticket = 0;
        if ($month_time >= time()) {
            $is_ticket = 1;
        }

        $order['is_ticket'] = $is_ticket;
        return $order;
    }

    /**
     * 供应商查看订单详情
     */
    public static function getSupplierOrderDetail($order_id, $shop_supplier_id)
    {
        $model = new static();
        $order = $model->where(['order_id' => $order_id, 'shop_supplier_id' => $shop_supplier_id])->with(['product' => ['image', 'refund'], 'address', 'express', 'extractStore', 'supplier', 'advance'])->find();
        if (empty($order)) {
            throw new BaseException(['msg' => '订单不存在']);
        }
        return $order;
    }

    /**
     * 余额支付标记订单已支付
     */
    public function onPaymentByBalance($orderNo, $data)
    {
        // 获取订单详情
        $PaySuccess = new MasterPaySuccessService($orderNo, $data);
        // 发起余额支付
        $status = $PaySuccess->onPaySuccess(OrderPayTypeEnum::BALANCE);
        if (!$status) {
            $this->error = $PaySuccess->getError();
        }
        return $status;
    }

    /**
     * 构建微信支付请求
     */
    protected static function onPaymentByWechat($user, $order_no, $pay_source, $online_money, $multiple)
    {
        return PaymentService::wechat(
            $user,
            $order_no,
            OrderTypeEnum::MASTER,
            $pay_source,
            $online_money,
            $multiple
        );
    }

    /**
     * 构建支付宝请求
     */
    protected static function onPaymentByAlipay($user, $order_no, $pay_source, $online_money, $multiple)
    {
        return PaymentService::alipay(
            $user,
            $order_no,
            OrderTypeEnum::MASTER,
            $pay_source,
            $online_money,
            $multiple
        );
    }

    /**
     * 待支付订单详情
     */
    public static function getPayDetail($orderNo)
    {
        $model = new static();
        return $model->where(['trade_no' => $orderNo, 'pay_status' => 10, 'is_delete' => 0])->with(['product', 'user', 'advance'])->find();
    }

    /**
     * 构建支付请求的参数
     */
    public static function onOrderPayment($user, $order_no, $payType, $pay_source, $online_money, $multiple)
    {
        //如果来源是h5,首次不处理，payH5再处理
//        if ($pay_source == 'h5') {
//            return [];
//        }
        if ($payType == OrderPayTypeEnum::WECHAT) {
            return self::onPaymentByWechat($user, $order_no, $pay_source, $online_money, $multiple);
        }
        if ($payType == OrderPayTypeEnum::ALIPAY) {
            return self::onPaymentByAlipay($user, $order_no, $pay_source, $online_money, $multiple);
        }
        return [];
    }

    /**
     * 判断当前订单是否允许核销
     */
    public function checkExtractOrder(&$order)
    {
        if (
            $order['pay_status']['value'] == OrderPayStatusEnum::SUCCESS
            && $order['delivery_type']['value'] == DeliveryTypeEnum::EXTRACT
            && $order['delivery_status']['value'] == 10
        ) {
            return true;
        }
        $this->setError('该订单不能被核销');
        return false;
    }

    /**
     * 当前订单是否允许申请售后
     */
    public function isAllowRefund()
    {
        // 必须是已发货的订单
        if ($this['delivery_status']['value'] != 20) {
            return false;
        }
        // 允许申请售后期限(天)
        $refundDays = SettingModel::getItem('trade')['order']['refund_days'];
        // 不允许售后
//        if ($refundDays == 0) {
//            return false;
//        }
        // 当前时间超出允许申请售后期限
//        if (
//            $this['receipt_status'] == 20
//            && time() > ($this['receipt_time'] + ((int)$refundDays * 86400))
//        ) {
//            return false;
//        }
        return true;
    }

    /**
     * 获取活动订单
     * 已付款，未取消
     */
    public static function getPlusOrderNum($user_id, $product_id, $order_source)
    {
        $model = new static();
        return $model->alias('order')->where('order.user_id', '=', $user_id)
            ->join('order_product', 'order_product.order_id = order.order_id', 'left')
            ->where('order_product.product_source_id', '=', $product_id)
//            ->where('order.pay_status', '=', 20)
            ->where('order.order_source', '=', $order_source)
            ->where('order.order_status', '<>', 20)
            ->sum('total_num');
    }

    /**
     * 累计成交笔数
     */
    public static function getTotalPayOrder($shop_supplier_id)
    {
        //累积成交笔数
        return (new static())->where('shop_supplier_id', '=', $shop_supplier_id)
            ->where('pay_status', '=', 20)
            ->where('order_status', 'in', [10, 30])
            ->count();
    }

    /**
     * 累计付款笔数
     */
    public static function getUserTotalPayOrder($user_id)
    {
        //累积成交笔数
        return (new static())->where('user_id', '=', $user_id)
            ->where('pay_status', '=', 20)
            ->where('order_status', 'in', [10, 30])
            ->count();
    }

    public static function getTodayPayOrder($shop_supplier_id)
    {
        //开始
        $beginToday = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
        //结束
        $endToday = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')) - 1;
        //今日成交笔数
        return (new static())->where('shop_supplier_id', '=', $shop_supplier_id)
            ->where('pay_status', '=', 20)
            ->where('order_status', 'in', [10, 30])
            ->whereBetweenTime('create_time', $beginToday, $endToday)
            ->count();
    }

    /**
     * 设置错误信息
     */
    protected function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 是否存在错误
     */
    public function hasError()
    {
        return !empty($this->error);
    }

    /**
     * 获取直播订单
     */
    public function getLiveOrder($params)
    {
        $model = $this;
        if (isset($params['room_id']) && $params['room_id']) {
            $model = $model->where('room_id', '=', $params['room_id']);
        }
        if (isset($params['pay_status']) && $params['pay_status']) {
            $model = $model->where('pay_status', '=', $params['pay_status']);
        }
        return $model->with(['product.image'])
            ->where('shop_supplier_id', '=', $params['shop_supplier_id'])
            ->where('room_id', '>', 0)
            ->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc'])
            ->paginate($params);
    }

    /**
     * 主订单购买的数量
     * 未取消的订单
     */
    public static function getHasBuyOrderNum($user_id, $product_id)
    {
        $model = new static();
        return $model->alias('order')->where('order.user_id', '=', $user_id)
            ->join('order_product', 'order_product.order_id = order.order_id', 'left')
            ->where('order_product.product_id', '=', $product_id)
            ->where('order.order_source', '=', OrderSourceEnum::MASTER)
            ->where('order.order_status', '<>', 20)
            ->sum('total_num');
    }

    /**
     * 获取订单信息
     */
    public static function orderInfo($order_id, $user)
    {
        $orderID = explode(',', $order_id);
        $multiple = 0;
        if (count($orderID) > 0) {
            $payPrice = OrderModel::where('order_id', 'in', $orderID)
                ->where('user_id', '=', $user['user_id'])
                ->where('pay_status', '=', 10)
                ->sum('pay_price');
            $multiple = 1;
        } else {
            $payDetail = OrderModel::where('order_id', '=', $orderID)
                ->where('pay_status', '=', 10)
                ->find();
            $payPrice = $payDetail['pay_price'];
        }
        $payInfo['order_id'] = $orderID;
        $payInfo['pay_price'] = $payPrice;
        $payInfo['multiple'] = $multiple;
        $payInfo['app_id'] = self::$app_id;
        return $payInfo;
    }

    /**
     * 创建订单支付信息
     */
    public function OrderPay($user, $params)
    {
        $payType = $params['payType'];
        $payment = '';
        $online_money = 0;
        $orderID = explode(',', $params['order_id']);
        //$order_no = $this->orderNo(); kevin 20240607 (这不是当前待支付的订单号)
        $order_no = $this -> where('order_id',$params['order_id']) -> value('order_no');
//        $multiple = 0;
//        $orderInfo = "";
        $payPrice = OrderModel::where('order_id', 'in', $orderID)
            ->where('user_id', '=', $user['user_id'])
            ->where('pay_status', '=', 10)
            ->sum('pay_price');
        OrderTradeModel::where('order_id', 'in', $orderID)
            ->where('pay_status', '=', 10)
            ->update(['balance' => 0, 'online_money' => 0, 'out_trade_no' => $order_no]);
        $multiple = 1;
        // 余额支付标记余额抵扣
        if ($params['use_balance'] == 1 || $payPrice <= 0) {
            if ($user['balance'] >= $payPrice) {
                $payType = 10;
//                if ($multiple == 1) {
                OrderTradeModel::where('order_id', 'in', $orderID)
                    ->where('pay_status', '=', 10)
                    ->update(['balance' => $payPrice]);
//                } else {
//                    $orderInfo->save(['balance' => $payPrice]);
//                }
                $data['multiple'] = $multiple;
                $this->onPaymentByBalance($order_no, $data);
            } else {
                if ($payType <= 10) {
                    $this->error = '用户余额不足';
                    return false;
                }
                $online_money = round($payPrice - $user['balance'], 2);
//                if ($multiple == 1) {
                OrderTradeModel::where('order_id', 'in', $orderID)
                    ->where('pay_status', '=', 10)
                    ->update(['balance' => $user['balance'], 'online_money' => $online_money]);
//                } else {
//                    $orderInfo->save(['balance' => $user['balance'], 'online_money' => $online_money]);
//                }
            }
        } else {
            if ($payType <= 10) {
                $this->error = '请选择支付方式';
                return false;
            }
            $online_money = $payPrice;
//            if ($multiple == 1) {
            OrderTradeModel::where('order_id', 'in', $orderID)
                ->where('pay_status', '=', 10)
                ->update(['online_money' => $online_money]);
//            } else {
//                $orderInfo->save(['online_money' => $online_money]);
//            }
        }
        if ($params['pay_source'] == 'wx') {
            //微信支付
            $online_money > 0 && $payment = self::onOrderPayment($user, $order_no, $payType, $params['pay_source'], $online_money, $multiple);
            //lakala微信支付
//            $online_money > 0 && $payment = self::lakalaOrderPayment($user, $order_no, $online_money);
            //lakala收银台
//            $online_money > 0 && $payment = self::lakalaCashierDesk($user, $order_no, $online_money);
        } elseif($params['pay_source'] == 'h5') {
            $online_money > 0 && $payment = self::onOrderPayment($user, $order_no, $payType, $params['pay_source'], $online_money, $multiple);
        }

        $result['order_id'] = $params['order_id'];
        $result['payType'] = $payType;
        $result['payment'] = $payment;
        $result['order_no'] = $order_no;
        $result['pay_price'] = $payPrice;
        $result['use_balance'] = $params['use_balance'];
        $result['is_join'] =  EuropeanUserPicking::updateOrderData($params['order_id'],2);
        return $result;
    }

//    public function OrderPayBlack($user, $params)
//    {
//        $payType = $params['payType'];
//        $payment = '';
//        $online_money = 0;
//        $orderID = explode(',', $params['order_id']);
//        $order_no = $this->orderNo();
//        $multiple = 0;
//        $orderInfo = "";
//        if (count($orderID) > 1) {
//            $payPrice = OrderModel::where('order_id', 'in', $orderID)
//                ->where('user_id', '=', $user['user_id'])
//                ->where('pay_status', '=', 10)
//                ->sum('pay_price');
//            OrderTradeModel::where('order_id', 'in', $orderID)
//                ->where('pay_status', '=', 10)
//                ->update(['balance' => 0, 'online_money' => 0, 'out_trade_no' => $order_no]);
//            $multiple = 1;
//        } else {
//            $orderInfo = OrderModel::where('order_id', 'in', $orderID)
//                ->where('pay_status', '=', 10)
//                ->find();
//            $orderInfo->save(['balance' => 0, 'online_money' => 0, 'trade_no' => $order_no]);
//            $payPrice = $orderInfo['pay_price'];
//        }
//        // 余额支付标记余额抵扣
//        if ($params['use_balance'] == 1) {
//            if ($user['balance'] >= $payPrice) {
//                $payType = 10;
//                if ($multiple == 1) {
//                    OrderTradeModel::where('order_id', 'in', $orderID)
//                        ->where('pay_status', '=', 10)
//                        ->update(['balance' => $payPrice]);
//                } else {
//                    $orderInfo->save(['balance' => $payPrice]);
//                }
//                $data['multiple'] = $multiple;
//                $this->onPaymentByBalance($order_no, $data);
//            } else {
//                if ($payType <= 10) {
//                    $this->error = '用户余额不足';
//                    return false;
//                }
//                $online_money = round($payPrice - $user['balance'], 2);
//                if ($multiple == 1) {
//                    OrderTradeModel::where('order_id', 'in', $orderID)
//                        ->where('pay_status', '=', 10)
//                        ->update(['balance' => $user['balance'], 'online_money' => $online_money]);
//                } else {
//                    $orderInfo->save(['balance' => $user['balance'], 'online_money' => $online_money]);
//                }
//            }
//        } else {
//            if ($payType <= 10) {
//                $this->error = '请选择支付方式';
//                return false;
//            }
//            $online_money = $payPrice;
//            if ($multiple == 1) {
//                OrderTradeModel::where('order_id', 'in', $orderID)
//                    ->where('pay_status', '=', 10)
//                    ->update(['online_money' => $online_money]);
//            } else {
//                $orderInfo->save(['online_money' => $online_money]);
//            }
//        }
//        if ($params['pay_source'] == 'wx') {
////            $online_money > 0 && $payment = self::onOrderPayment($user, $order_no, $payType, $params['pay_source'], $online_money, $multiple);
//            $online_money > 0 && $payment = self::lakalaOrderPayment($user, $order_no, $online_money);
//        } else {
//
//        }
//
//        $result['order_id'] = $params['order_id'];
//        $result['payType'] = $payType;
//        $result['payment'] = $payment;
//        $result['order_no'] = $order_no;
//        $result['pay_price'] = $payPrice;
//        $result['use_balance'] = $params['use_balance'];
//        return $result;
//    }

    /**
     * 获取尾款订单数据
     */
    public static function getFinalDetail($order_id)
    {
        $detail = self::detail($order_id);
        $detail['product'][0]['product_image'] = $detail['product'][0]['image']['file_path'];
        $detail['product'][0]['reduce_money'] = $detail['advance']['reduce_money'];
        $supplierData[] = [
            'shop_supplier_id' => $detail['shop_supplier_id'],
            'supplier' => $detail['supplier'],
            'productList' => $detail['product'],
            'order' => $detail
        ];
        return $supplierData;
    }

    private function formatPayEndTime($leftTime)
    {
        if ($leftTime <= 0) {
            return '';
        }
        $str = '';
        $day = floor($leftTime / 86400);
        $hour = floor(($leftTime - $day * 86400) / 3600);
        $min = floor((($leftTime - $day * 86400) - $hour * 3600) / 60);

        if ($day > 0) $str .= $day . '天';
        if ($hour > 0) $str .= $hour . '小时';
        if ($min > 0) $str .= $min . '分钟';
        return $str;
    }

    public static function lakalaOrderPayment($user, $order_no, $online_money)
    {
        $lakalService = new LakalaPaymentService();
        $openid = $user['open_id'];
        return $lakalService->payOrder($openid, $order_no, $online_money);
    }

    public static function lakalaCashierDesk($user, $order_no, $online_money)
    {
        $lakalService = new LakalaPaymentService();
        $openid = $user['open_id'];
        return $lakalService->lakalaCashierDesk($openid, $order_no, $online_money);
    }


    public function shopperReceiving($where, $user)
    {
//        $shopper = Shopper::shopperDetail($user['user_id']);
//        if (empty($shopper)) throw new Exception('用户不是配送员');
        $order = $this->where(['order_id' => $where['order_id']])->find();

        $shopper = Shopper::shopperDetail($user['user_id']);
        $is_single = 0;
        if ($shopper) {
            $is_single = 1;
        }
        $order->save([
            'is_shipping' => 1,
            'shipping_time' => time(),
            'transfer_oktime' => time(),
            'is_clerk_shipping' => 1,
            'is_single' => $is_single

        ]);
    }


    public function receiving($where, $user)
    {

        $file = 'example.txt'; // 要锁定的文件
        $lock = fopen($file, 'w+'); // 创建一个可写的文件句柄

        if (flock($lock, LOCK_EX)) { // 获取独占锁
            $clerk = Clerk::getByUser($user);
            if (empty($clerk)) throw new Exception('用户不是配送员');
            $order = $this->where(['order_id' => $where['order_id']])->find();
            if($order['store_clerk_id']){
                if (empty($clerk)) throw new Exception('该订单已被接');
            }
            $now = time();


            $order->save([
                'store_clerk_id' => $clerk['clerk_id'],
                'delivery_status' => 20,
                'receipt_status' => 10,
                'order_status' => 10,
                'delivery_time' => $now,
                'is_clerk_shipping' => 1,
                'is_shipping' => 1,
            ]);

            $this->addUserIdJson($clerk['clerk_id'], $order['order_id'], $order['user_id_json']);


            //发送下单用户短信通知
            $time = DicModel::listAll(['type' => 'sendTime'], [], 'sort_num desc');

            if ($order['yypstime']) {
                $newTimestamp = $order['yypstime'];
            } else {
                $newTimestamp = strtotime('+' . $time[0]['value'] . ' minutes', $now); // 将当前时间戳加上19分钟
            }
            $send_time = date("H:i", $newTimestamp);
    //        $smsConfig = \app\common\model\settings\Setting::getItem('sms', '10001');
            $user = User::detail(['user_id' => $order['user_id']]);
            $name = $clerk['real_name'];
            if (!empty($user['mobile'])) {
                $send_data = [
                    'name' => $name,
                    'time' => $send_time
                ];
                //@author libh
                //@date 2024-5-14
                (new Sms())->sendSms($user['mobile'], 'SMS_464470281', 'ORDER_NOTICE', $send_data, $order["shop_supplier_id"]);

    //            $send_template = 'SMS_464470281';
    //            $SmsDriver     = new SmsDriver($smsConfig);
    //            $mobile        = $user['mobile'];
    //            $send_data     = [
    //                'name' => $name,
    //                'time' => $send_time
    //            ];
    //           $SmsDriver->sendSms($mobile, $send_template, $send_data);
            }
            flock($lock, LOCK_UN); // 释放锁
        } else {
            echo "无法获取文件锁";
        }

        fclose($lock); // 关闭文件句柄
    }

    /**
     * 根据经纬度查询是否有附近商家（米）
     * @param $where
     * @return array
     */
    public static function checkScope($where)
    {
        $distance = self::getDistanceDic();
        if (isset($where['latitude']) && isset($where['longitude'])) {
            $result = Store::minDistance($where['longitude'], $where['latitude']);
        } else {
            // 20240412 joey 判断商户门店是否在范围内
            $result = Db::query("SELECT
                         s.*,
                        (st_distance (point (s.longitude, s.latitude), point(?, ?) ) * 111195) as distance
                        FROM
                        jjjshop_store as s
                        WHERE s.is_delete = 0 and s.status = 1 and s.check_store = 1 and s.shop_supplier_id = ?
                        HAVING distance < ?
                        ORDER BY distance", [$where['longitude'], $where['latitude'], $where['shop_supplier_id'], $distance]);
        }
        $list = [];
        $coord = [$where['latitude'], $where['longitude']];
        $lkey = 0;
        foreach ($result as $item) {
            if (self::AllcheckPointInPolygon($item, $where, $distance)) {
                $list[$lkey] = $item;
                $lkey++;
            }
            // if (isset($item['scope_coordinates']) && $item['scope_coordinates']) {
            //     $item['scope_coordinates'] = is_array($item['scope_coordinates']) ? $item['scope_coordinates'] : json_decode($item['scope_coordinates'], true);
            //     if (pointInPolygon($coord, $item['scope_coordinates'])) {
            //         $list[$lkey] = $item;
            //         $lkey++;
            //     }
            // } else {
            //     $GetDis                         = [];
            //     $GetDis['async_lat']            = $where['latitude'];
            //     $GetDis['async_lng']            = $where['longitude'];
            //     $GetDis['address']['latitude']  = $item['latitude'];
            //     $GetDis['address']['longitude'] = $item['longitude'];
            //     $RespDis                        = self::orderDistance($GetDis);
            //     if ($RespDis <= $distance) {

            //     }
            // }
        }
        return $list;
    }

    /**
     * @Exp    查找最近商家
     * @param $where
     * @return [type]     [description]
     */
    public static function checkMiniStore($where)
    {
        if (isset($where['latitude']) && isset($where['longitude'])) {
            return Store::minDistance($where['longitude'], $where['latitude']);
        }
        return [];
    }

    /**
     * @Exp    检查是否进入范围
     * @Author Mr.Z
     * @param Array $Store [门店]
     * @param Array $Point [点]
     * @param integer $Distance [直线距离]
     */
    private static function AllcheckPointInPolygon($Store, $Point, $Distance = 1000)
    {
        if (isset($Store['scope_coordinates']) && $Store['scope_coordinates']) {
            $coord = [$Point['latitude'], $Point['longitude']];
            $CheckStore = [];
            $CheckStore['scope_coordinates'] = is_array($Store['scope_coordinates']) ? $Store['scope_coordinates'] : json_decode($Store['scope_coordinates'], true);
            if (pointInPolygon($coord, $CheckStore['scope_coordinates'])) {
                return true;
            }
        } else {
            $GetDis = [];
            $GetDis['async_lat'] = $Point['latitude'];
            $GetDis['async_lng'] = $Point['longitude'];
            $GetDis['address']['latitude'] = $Store['latitude'];
            $GetDis['address']['longitude'] = $Store['longitude'];
            $RespDis = self::orderDistance($GetDis);
            if ($RespDis <= $Distance) {
                return true;
            }
        }
        return false;
    }

    public static function checkScopeAll($where)
    {
        return Db::query("SELECT
                         s.*,
                        (st_distance (point (s.longitude, s.latitude), point(?, ?) ) * 111195) as distance
                        FROM
                        jjjshop_store as s
                        WHERE s.is_delete = 0 and s.status = 1 and s.check_store = 1
                        ORDER BY distance", [$where['longitude'], $where['latitude']]);
    }

    /**
     * @Exp    检测配送地址是否在门店范围
     * @Author Mr.Z
     * @param  [type]     $address [地址Info]
     * @param integer $Storeid [门店ID]
     * @return [type]              [description]
     */
    public static function checkAddrPointToStore($address, $Storeid = 0)
    {
        if ($address['longitude'] && $address['latitude']) {
            $distance = self::getDistanceDic();
            $Store = Store::detail($Storeid);
            if ($Store) {
                return self::AllcheckPointInPolygon($Store, $address, $distance);
            }
        }
        return false;
    }

    /**
     * @Exp 检测配送地址是否在商户所有门店范围
     * @Auth Mr.Z
     * @Date 2024/7/11
     * @param $address [地址Info]
     * @param $shop_supplier_id [商户ID]
     * @return bool
     */
    public static function checkAddrPointToSupplier($address, $shop_supplier_id = 0)
    {
        if ($address['longitude'] && $address['latitude']) {
            $distance = self::getDistanceDic();
            $StoreList = (new Store())->where('is_delete', '=', '0')
                ->where('shop_supplier_id', '=', $shop_supplier_id)
                ->order(['sort' => 'asc', 'create_time' => 'desc'])
                ->select();
            foreach ($StoreList as $Store){
                $Response = self::AllcheckPointInPolygon($Store, $address, $distance);
                if($Response){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @Exp    检测门店是否与商品同属
     * @Author Mr.Z
     * @param  [type]     $Storeid [门店ID]
     * @param  [type]     $Produts [商品组]
     * @return [type]              [description]
     */
    public static function checkStoreWithProduct($Storeid, $Produts = [])
    {
        $Store = Store::detail($Storeid);
        if ($Store) {
            foreach ($Produts as $Pval) {
                if ($Pval['shop_supplier_id'] != $Store['shop_supplier_id']) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * @Exp    检测店铺休息
     * @Author Mr.Z
     * @Date   2024-04-26
     * @param  [type]     $Storeid [店铺id]
     * @return [type]              [description]
     */
    public static function checkStoreRest($Storeid)
    {
        $Store = Store::detail($Storeid);
        if ($Store) {
            // 改门店休息
            // if($Store['business_status']==1){
            //     return true;
            // }
            $SupplierRs = Supplier::detail($Store['shop_supplier_id']);
            if ($SupplierRs) {
                if ($SupplierRs['business_status'] == 1) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @Exp 检测商户起送价
     * @Auth Mr.Z
     * @Date 2024/6/28
     * @param $orderInfo
     * @return bool 未达到：false，达到：true
     */
    public static function checkStoreDelyPrice($orderInfo = [])
    {
        $shop_supplier_id = $orderInfo['supplierList'][0]['shop_supplier_id']??0;
        $yourprices = $orderInfo['orderData']['order_pay_price']??0;
        $yourprices<0 && $yourprices=0;
        $SupplierRs = Supplier::detail($shop_supplier_id);
        if ($SupplierRs) {
            if ($SupplierRs['delivery_price'] > $yourprices) {
                return bcsub($SupplierRs['delivery_price'],$yourprices,2);
            }
        }
        return 0;
    }

    /**
     * @Exp    检测用户地址是否在收货范围
     * @param $user_id
     * @param $ShopSupplierId
     * @param $DefaultAid
     * @return array
     */
    public static function checkUserAllAddress($user_id = 0, $ShopSupplierId = 0, $DefaultAid = 0)
    {
        $distance = self::getDistanceDic();
        $Return_Aid = 0;
        $ChangeStore = 0;
        //所有收货地址
        $model = new UserAddress;
        $Addresslist = $model->getList($user_id);
        if ($ShopSupplierId) {
            //检测所有地址是不是在门店配送范围
            foreach ($Addresslist as $Akey => $Aitem) {
                //检测门店
                $StoreCk = self::checkAddressDelivery($Aitem, $ShopSupplierId, 0, $distance, 0);
                if($StoreCk){
                    $Aid = $Aitem['address_id'];
                    //默认的
                    if ($Aid == $DefaultAid) {
                        $ChangeStore = $StoreCk;
                        $Return_Aid = $Aid;
                        break;
                    }
                    if ($Return_Aid == 0) {
                        $ChangeStore = $StoreCk;
                        $Return_Aid = $Aid;
                    }
                }
            }
        }
        if($Return_Aid==0){
            //检测所有地址是不是在城市配送范围
            foreach ($Addresslist as $Akey=>$Aitem){
                //检测城市
                $Supplier = Supplier::detail($ShopSupplierId);
                $StoreCk = self::checkAddressDelivery($Aitem, 0, $Supplier['city_id'], $distance, 1);
                if($StoreCk){
                    $Aid = $Aitem['address_id'];
                    //默认的
                    if($Aid == $DefaultAid){
                        $ChangeStore = $StoreCk;
                        $Return_Aid = $Aid;
                        break;
                    }
                    if($Return_Aid==0) {
                        $ChangeStore = $StoreCk;
                        $Return_Aid = $Aid;
                    }
                }
            }
        }
        return [$Return_Aid,$ChangeStore];
    }

    /**
     * @Exp    配送范围
     * @return int|mixed
     */
    public static function getDistanceDic(){
        $list = DicModel::listAll(['type' => 'distance'], [], 'sort_num desc');
        if (count($list) > 0) {
            $distance = $list[0]['value'];
        } else {
            $distance = 5000;
        }
        return $distance;
    }

    /**
     * @Exp    检测配送
     * @param $Address 地址信息
     * @param $ShopSupplierId 商户id
     * @param $CityId 城市id
     * @param $Distance 配送距离
     * @param $CKtype 类型：0检索指定商户，1检索指定城市，2检索全站
     * @return int|mixed
     */
    public static function checkAddressDelivery($Address, $ShopSupplierId = 0, $CityId = 0, $Distance = 1000, $CKtype = 2){
        if($CKtype==0){
            $StoreList = (new Store)->getList(null, '', '', false, $ShopSupplierId, []);
            foreach ($StoreList as $key => $Store){
                if(self::AllcheckPointInPolygon($Store, $Address, $Distance)){
                    return $Store['store_id'];
                }
            }
        }else{
            $TempCityId = $CKtype==1?$CityId:$Address['city_id'];
            if($CKtype==2){
                $Distance = self::getDistanceDic();
            }
            $StoreList = (new Store)->getList(null, '', '', false, 0, ['city_id' => $TempCityId]);
            foreach ($StoreList as $key => $Store){
                if(self::AllcheckPointInPolygon($Store, $Address, $Distance)){
                    return $Store['store_id'];
                }
            }
        }
        return 0;
    }

    public static function orderDistance($order)
    {
        // 将角度转换为弧度
        $degToRad = M_PI / 180;

        // 地球平均半径（单位：米）
        $earthRadius = 6371000;

        $lat1 = $order['async_lat'];
        $lon1 = $order['async_lng'];
        $lat2 = $order['address']['latitude'];
        $lon2 = $order['address']['longitude'];

        // 将经纬度转换为弧度
        $lat1 *= $degToRad;
        $lon1 *= $degToRad;
        $lat2 *= $degToRad;
        $lon2 *= $degToRad;

        // 应用Haversine Formula计算距离
        $dLat = ($lat2 - $lat1);
        $dLon = ($lon2 - $lon1);
        $a = pow(sin($dLat / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($dLon / 2), 2);
        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        $distance = $earthRadius * $c;

        return round($distance, 2); // 返回结果保留小数点后两位
    }

    /**
     * 配送完成接口
     * @param $where
     * @param $user
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function deliveryCompleted($where, $user, $shopper = false)
    {
        $model = new static();
        $order = $model->where(['order_id' => $where['order_id']])->find();

        if (empty($order)) throw new Exception("订单不存在");
        if ($shopper) {
            $Soper = Shopper::getByUser($user);
            if (empty($Soper)) throw new Exception("用户不是配送员");
            if ($order['store_clerk_id'] != $Soper['id']) throw new Exception("订单异常");
        } else {
            $clerk = Clerk::getByUser($user);
            if (empty($clerk)) throw new Exception("用户不是配送员");
            if ($order['store_clerk_id'] != $clerk['clerk_id']) throw new Exception("订单异常");
        }
        $filter['is_comment'] = 0;
        $filter['order_status'] = 30;
        $order_create_time = strtotime($order['create_time']);
        $coupon_id_sys = $order['coupon_id_sys'];
        $total_price = $order['total_price'];

        $order->save([
            "delivery_image" => $where['delivery_image'] ?? '',
            'is_comment' => 0,
            'order_status' => 30,
            'receipt_status' => 20,
            'receipt_time' => time()
        ]);
        //分佣记录
        $supplier_commission['shop_supplier_id'] = $order['shop_supplier_id'];
        $supplier_commission['order_id'] = $order['order_id'];
        $supplier_commission['order_no'] = $order['order_no'];
        $supplier_commission['pay_time'] = $order['pay_time'];
        $supplier_commission['pay_price'] = $order['pay_price'];
        $supplier_commission['user_id'] = $order['user_id'];
        $supplier_commission['order_source'] = $order['order_source'];
        $supplier_commission['order_create_time'] = $order_create_time;
        $supplier_commission['coupon_id_sys'] = $coupon_id_sys;
        $supplier_commission['total_price'] = $total_price;

        $list = (new \app\api\model\order\OrderProduct())->where('order_id', $order['order_id'])->select()->toArray();
        SupplierCommission::createProductData($list, $supplier_commission);


        //推荐订单
        try {
            $tresponse = OrderRefereeModel::RefereeOrderCompleted($order);
            //20240314 joey 推广奖励优惠券
            (new OrderCompleteService())->onOrderNumCoupon([$order]);
            //20240409 joey 购买商品赠送优惠券
            self::giveCoupon($order);
        } catch (\Exception $e) {
            log_write('写入错误：' . $e->getMessage());
        }
        if ($tresponse) {
            $UserModel = new UserModel();
            $refrs = $UserModel->where('user_id', '=', $order['user_id'])->find();
            if ($refrs) $UserModel->sumInviteMoney($refrs['referee_id'], $order['pay_price']);
        }
        //发送下单用户短信通知
//        $smsConfig = \app\common\model\settings\Setting::getItem('sms', '10001');
//        $user = User::detail(['user_id' => $order['user_id']]);
//        if (!empty($user['mobile'])) {
//            $send_template = 'SMS_464445306';
//            $SmsDriver = new SmsDriver($smsConfig);
//            $mobile = $user['mobile'];
//            $send_data = [
//                'name' => 'name'
//            ];
//            $SmsDriver->sendSms($mobile, $send_template, $send_data);
//        }
    }

    public static function asyncSaveCoord($params)
    {
        $model = new static();
        $order = $model->where(['order_id' => $params['order_id']])->find();
        if ($order['pay_status']['value'] == OrderPayStatusEnum::SUCCESS) {
            $order->save([
                'async_lng' => $params['async_lng'],
                'async_lat' => $params['async_lat']
            ]);
        } else {
            throw new Exception("订单状态异常");
        }

    }

    public static function asyncGetCoord($params)
    {
        $model = new static();
        return $model->where(['order_id' => $params['order_id']])->findOrFail();
    }


    /**
     * 将订单写入redis用于查询是是否接单
     * @param $order_id
     * @return void
     */
    public function insertRedisOrder($order_id)
    {

        if ($order_id) {
            $Redis = new \think\cache\driver\Redis(config('cache.stores.redis'));
            //expire_time为列队名称
            $expire_time = time() + 3 * 60;//到期时间(下单后3分钟到期)
            $Redis->zAdd('expire_time', $expire_time, $order_id);
        }

    }

    /**
     *
     * 获取redis超时未接单的订单
     * @return void
     */
    public function getRedisOrder()
    {
        //file_put_contents('redis_order.txt','获取redis超时未接单的订单------------'.date('Y-m-d H:i:s') . "\r\n", FILE_APPEND);
        $Redis = new \think\cache\driver\Redis(config('cache.stores.redis'));
        $res = $Redis->zRangeByScore('expire_time', 0, time());
        //存在数据说明已到期
        if (count($res) > 0) {
            foreach ($res as $k => $v) {
                $order_ids[] = $res[$k]; //订单id
                //消费掉列队中的行数据
                $Redis->zRem('expire_time', $res[$k]);
            }
            $map = [];
            $map[] = ['delivery_status', '=', 20];
            $map[] = ['is_clerk_shipping', '=', 0];
            $map[] = ['order_id', 'in', $order_ids];
            $new_order_ids = $this->where($map)->column('order_id'); //过期未接单的订单id集合
            $this->canceltransferOrder($new_order_ids);
            unset($res);
        }
    }

    //取消订单
    public function canceltransferOrder($order_ids = [], $user = [])
    {

        $ProductClaimModel = new ProductClaim();
        $list = $this->where('order_id', 'in', $order_ids)->select();
        $uid = $user['user_id'] ?? '';
        $Redis = new \think\cache\driver\Redis(config('cache.stores.redis'));

        if ($list) {
            foreach ($list as $value) {
                $map = [];
                $map[] = ['store_clerk_id', '=', $value['store_clerk_id']];
                $map[] = ['order_id', '=', $value['order_id']];

                $ProductClaimModel->where($map)->delete(); //取消转单后删除转单记录
                $user_id_json = $this->where('order_id', $value['order_id'])->value('user_id_json');
                $user_id_array = json_decode($user_id_json, true);


                $count = count($user_id_array) - 3;
                $user_id = $user_id_array[$count] ?? 0; //转单人的id
                $is_transfer_ckid = 1;
                $transfer_ckid = 0;
                $transfer_spid = 0;
                if ($user_id) {
                    $clerk = (new Clerk())->where('user_id', $user_id)->find();
                    if (!$clerk) {
                        $clerk = (new Shopper())->where('uid', $user_id)->find();
                        $is_transfer_ckid = 2;
                        $transfer_spid = $value['transfer_spid'];
                        $transfer_ckid = $clerk['id'];
                    } else {
                        $is_transfer_ckid = 1;
                        $transfer_spid = $clerk['store_id'];
                        $transfer_ckid = $clerk['clerk_id'];
                    }
                }

                $Redis->zRem('expire_time', $value['order_id']);//清除redis记录

                $this->updateUserIdJson($value['store_clerk_id'], $value['order_id'], $value['user_id_json'], $value['is_store_clerk_id']);
                $this->where('order_id', $value['order_id'])->update([
                    'store_clerk_id' => $value['transfer_ckid'],
                    'store_id' => $value['transfer_spid'],
                    'transfer_ckid' => $transfer_ckid,
                    'transfer_spid' => $transfer_spid,
                    'transfer_ctime' => 0,
                    'is_clerk_shipping' => 1,
                    'is_clerk_claim' => cache($uid . '_' . $value['order_id']) ?: 0,
                    'is_claim' => $value['is_claim'],
                    'shopper_id' => 0,
                    'is_store_clerk_id' => $value['is_transfer_ckid'],
                    'is_transfer_ckid' => $is_transfer_ckid,
                ]);
            }
        }
        return true;

    }

    public function addUserIdJson($shopper_id = '', $order_id = '', $user_id_json = '', $is_store_clerk_id = 1)
    {

        if ($is_store_clerk_id == 2) {
            $user_id = (new Shopper())->where('id', $shopper_id)->value('uid');
        } else {
            $user_id = (new Clerk())->where('clerk_id', $shopper_id)->value('user_id');
        }
        if (!$user_id) {
            return true;
        }
        $map = [];
        $map[] = ['user_id_json', 'like', '%"' . $user_id . '"%'];
        $map[] = ['order_id','=',$order_id];
        if (!$this->where($map)->count()) {
            $user_id_array = json_decode($user_id_json, true);
            $user_id_array[] = (string)$user_id;
            $user_id_json = json_encode($user_id_array);
            $this->where('order_id', $order_id)->update(['user_id_json' => $user_id_json]);
        }
        return true;
    }

    public function updateUserIdJson($store_clerk_id, $order_id = '', $user_id_json = '', $is_store_clerk_id = 1)
    {
        if ($is_store_clerk_id == 2) {
            $user_id = (new Shopper())->where('id', $store_clerk_id)->value('uid');
        } else {
            $user_id = (new Clerk())->where('clerk_id', $store_clerk_id)->value('user_id');
        }

        if (!$user_id) {
            return true;
        }
        $user_id_array = json_decode($user_id_json, true);
        if ($user_id_array) {
            foreach ($user_id_array as $k => $v) {
                if ($v == $user_id) {
                    unset($user_id_array[$k]);
                }
            }
        }
        $user_id_array = array_values($user_id_array);
        $user_id_json = json_encode($user_id_array);
        $this->where('order_id', $order_id)->update(['user_id_json' => $user_id_json]);
        return true;
    }

    //获取配送员信息
    public static function getDeliveryUser($store_clerk_id = '', $is = '')
    {
        if ($is == 1) {
            $clerk = (new Clerk())->where('clerk_id', $store_clerk_id)->find();
        } else {
            $clerk = (new Shopper())->where('id', $store_clerk_id)->find();
            $clerk['real_name'] = $clerk['username'];
        }

        return $clerk;
    }

    public function updateOrderUserIdJson1($user_id)
    {
        $map = [];
        $map[] = ['pay_status', '=', OrderPayStatusEnum::SUCCESS];
//        $map[] = ['delivery_status','=',20];
//        $map[] = ['order_status','=',10];
//        $map[] = ['receipt_status','=',10];
//        $map[] = ['user_id','=',$user_id];
        $list = $this->where($map)->select();
        foreach ($list as $key => $value) {
            $this->addUserIdJson($value['store_clerk_id'], $value['order_id'], $value['user_id_json'], $value['is_store_clerk_id']);

        }
        return true;

    }

    public function updateOrderUserIdJson2($user_id)
    {
        $map = [];
        $map[] = ['pay_status', '=', OrderPayStatusEnum::SUCCESS];
//        $map[] = ['delivery_status','=',20];
//        $map[] = ['order_status','=',10];
//        $map[] = ['receipt_status','=',10];
//        $map[] = ['user_id','=',$user_id];
        $list = $this->where($map)->select();
        foreach ($list as $key => $value) {
            $this->addUserIdJson($value['transfer_ckid'], $value['order_id'], $value['user_id_json'], $value['is_transfer_ckid']);
        }
        return true;

    }


    /**
     * 订单收货完成赠送优惠券
     * @param $order
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Author joey
     * @date 2024/4/9 11:02
     */
    public static function giveCoupon($order)
    {
        $model = static::with(['product.product'])->find($order['order_id']);
        if (!$model) {
            return false;
        }

        foreach ($model['product'] as $item) {
            if (isset($item['product']['give_coupon_id']) && $item['product']['give_coupon_id'] > 0 && isset($item['product']['give_coupon_num']) && $item['product']['give_coupon_num'] > 0) {
                (new UserCoupon)->giveUserCoupon($item['product']['give_coupon_id'], $order['user_id'], $item['product']['give_coupon_num'], $item['total_num']);
            }
        }
        return true;
    }

}
